package cn.itsource.hrm.service.impl;

import cn.itsource.hrm.constants.RedisKeyConstants;
import cn.itsource.hrm.domain.CourseType;
import cn.itsource.hrm.feignclients.PageStaticFeignClient;
import cn.itsource.hrm.feignclients.RedisFeignClient;
import cn.itsource.hrm.mapper.CourseTypeMapper;
import cn.itsource.hrm.service.ICourseTypeService;
import cn.itsource.hrm.util.AjaxResult;
import cn.itsource.hrm.vo.CrumbsVO;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author sk
 * @since 2020-02-17
 */
@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {

    @Autowired
    private RedisFeignClient redisFeignClient;

    @Autowired
    private PageStaticFeignClient pageStaticFeignClient ;

    @Override
    public boolean insert(CourseType entity) {

        boolean insertSuccess = super.insert(entity);

        //重置Redis
        //查询mysql中的课程分类
        //把课程分类放到Redeis
        resetRedisForCourseType();

        //触发页面静态化
        triggerPageStatic();

        return insertSuccess;
    }

    @Override
    public boolean deleteById(Serializable id) {
        boolean deleteSuccess = super.deleteById(id);
        //重置Redis
        //查询mysql中的课程分类
        //把课程分类放到Redeis
        resetRedisForCourseType();

        //触发页面静态化
        triggerPageStatic();

        return deleteSuccess;
    }

    @Override
    public boolean updateById(CourseType entity) {
        boolean updateSuccess = super.updateById(entity);
        //重置Redis
        //查询mysql中的课程分类
        //把课程分类放到Redeis
        resetRedisForCourseType();

        //触发页面静态化
        triggerPageStatic();

        return updateSuccess;
    }

    //触发课程首页页面静态化： home.vm  -> $model.courseTypes
    public void triggerPageStatic(){
        //1.准备页面需要的数据，存储到Redis ： treeData
        List<CourseType> courseTypes = this.treeData();

        //2.准备参数：数据的redis的key和t_page的name
        String pageName = "home";

        //封装数据的map
        Map<String,Object> model = new HashMap<>();
        model.put("courseTypes",courseTypes);

        AjaxResult ajaxResult = redisFeignClient.set(RedisKeyConstants.COURSE_TYPES_PAGE_STATIC, JSON.toJSONString(model));
        if(!ajaxResult.isSuccess()){
            throw new RuntimeException("页面静态化数据准备失败"+ajaxResult.getMessage());
        }

        //3.通过Feign调用页面静态化服务,触发页面静态化
        AjaxResult ajaxResultPageStatic = pageStaticFeignClient.pageStatic(pageName, RedisKeyConstants.COURSE_TYPES_PAGE_STATIC);
        if(!ajaxResultPageStatic.isSuccess()){
            throw new RuntimeException("页面静态化失败："+ajaxResultPageStatic.getMessage());
        }
    }

    //重置Redis中的课程分类
    private  List<CourseType>  resetRedisForCourseType(){
        //        - 如果Reids没有就从Mysql中查
        List<CourseType> courseTypes = baseMapper.selectList(null);

        //        - Mysql查到之后同步一份到Redis
        redisFeignClient.set(RedisKeyConstants.COURSE_TYPE,JSON.toJSONString(courseTypes));
        return courseTypes;
    }

    //返回的 CourseType 有没有问题?
    //返回的List的size应该是多少？
    //怎么封装数据 :把所有的课程分类查询出来，然后再内存中进行数据结构的组装
    @Override
    public List<CourseType> treeData() {
        List<CourseType> courseTypes = null;
//        - 查询课程分类的时候先查询Redis
        AjaxResult ajaxResult = redisFeignClient.get(RedisKeyConstants.COURSE_TYPE);

        //判断是否有结果
        if(ajaxResult.isSuccess() && null != ajaxResult.getResultObj()){
            //Redis中有数据
            //- 如果Redis有就直接返回、
            String jsonFromRedis = ajaxResult.getResultObj().toString();

            //思考：存在redis中的数据 ，要不要有层级结构 :放没有处理过的list
            courseTypes = JSON.parseArray(jsonFromRedis , CourseType.class);
        }else{
            courseTypes = resetRedisForCourseType();
        }
        //1.查询所有的课程类型
        //List<CourseType> courseTypes = baseMapper.selectList(null);

        //2.先过滤出一级分类
        //用来封装一级分类，当然每个一级分类的children中有其子分类
        List<CourseType> primaryCourseType = new ArrayList<>();
        for(CourseType courseType : courseTypes){
            //如果pid==0那么久是一级分类
            if(courseType.getPid().longValue() == 0){
                primaryCourseType.add(courseType);//1037
            }else{
                //2.如果不是一级分类，就要知道自己的父分类，装到自己的父分类的 children
                //courseType :当前分类，根据当前分类的pid 就是父分类的id
                CourseType currentPrimaryCourseType = null; //1037
                for(CourseType pcourseType : courseTypes ){
                    if(courseType.getPid().longValue() == pcourseType.getId().longValue()){
                        //如果当前分类（courseType）的pid 和某个分类的id相等，那么这个某个分类就是当前分类的父分类
                        currentPrimaryCourseType = pcourseType;
                        break;
                    }
                }
                if(currentPrimaryCourseType != null){
                    //3.如果找到了父分类，就把当前分类加入父分类的children中
                    currentPrimaryCourseType.getChildren().add(courseType);
                }
            }
        }
        return primaryCourseType;
    }

    @Override
    public List<CrumbsVO> crumbs(Long id) {

        //1.根据课程分类查询所有父分类
        CourseType currentCourseType = baseMapper.selectById(id);

        //获取父级分类
        String path = currentCourseType.getPath();
        //去掉前面的 .
        path = path.startsWith(".")?path.substring(1):path;
        //去掉后面的 .
        path = path.endsWith(".")?path.substring(0,path.length()-1):path;
        //获取所有的父级分类
        String[] types = path.split("\\.");

        //结果
        List<CrumbsVO> result = new ArrayList<>();

        for(String type : types ){

            CrumbsVO vo = new CrumbsVO();

            Long typeId = Long.valueOf(type);

            CourseType courseType = baseMapper.selectById(typeId);

            //2.分类进行组装 ，一个分类一个CrumbsVO.ownerProductType
            vo.setOwnerProductType(courseType);

            //3.为每个分类查询其兄弟姐妹分类，设置到CrumbsVO.otherProductTypes
            Long pid = courseType.getPid();
            List<CourseType> otherCoutseTypes = baseMapper.selectByPid(pid);

            //4.删除自己
            Iterator<CourseType> iterator = otherCoutseTypes.iterator();
            while (iterator.hasNext()){
                if(iterator.next().getId().equals(courseType.getId())){
                    iterator.remove();
                    break;
                }
            }

            vo.setOtherProductTypes(otherCoutseTypes);

            result.add(vo);
        }

        return result;
    }
}